﻿// Util/JsonDataManager.cs
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using MultiDAQ_Analysis.Models;

namespace MultiDAQ_Analysis.Util
{
    /// <summary>
    /// JSON数据存储管理器（安装包/受限权限环境友好）
    /// </summary>
    public static class JsonDataManager
    {
        // 可选：允许通过环境变量或配置覆盖数据目录（比如企业部署）
        private const string EnvDataDir = "MULTIDAQ_DATA_DIR";

        private static readonly string DataDirectory = ResolveWritableDataDirectory();

        static JsonDataManager()
        {
            // 只创建，不在这里抛出致命异常
            try { Directory.CreateDirectory(DataDirectory); }
            catch (Exception ex)
            {
                // 这里不要让类型初始化失败。记录并继续，后续会兜底到 %TEMP%
                Console.WriteLine($"[DataDir] 创建失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 保存多轮测量数据到 JSON（原子写入）
        /// </summary>
        public static async Task SaveMultiRoundDataAsync(MultiRoundMeasurementData data)
        {
            if (data == null) throw new ArgumentNullException(nameof(data));

            string safeType = SanitizeForFileName(data.MeasurementType ?? "Unknown");
            string safeId = SanitizeForFileName(data.MeasurementId ?? "NA");
            string fileName = $"{safeType}_{data.StartTime:yyyyMMdd_HHmmss}_{safeId}.json";

            // 优先用主数据目录，不行则兜底
            string targetDir = EnsureDirectoryOrFallback(DataDirectory);
            string finalPath = Path.Combine(targetDir, fileName);
            string tmpPath = finalPath + ".tmp";

            var json = JsonConvert.SerializeObject(data, Formatting.Indented);

            try
            {
                // 用 FileStream 直接写 UTF8（无 BOM），并确保 Flush 到磁盘
                byte[] bytes = Encoding.UTF8.GetBytes(json);
                using (var fs = new FileStream(tmpPath, FileMode.Create, FileAccess.Write, FileShare.None,
                                               bufferSize: 64 * 1024, options: FileOptions.WriteThrough))
                {
                    await fs.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
                    await fs.FlushAsync().ConfigureAwait(false);
                    fs.Flush(true); // flush to disk
                }

                // 原子替换（优先 Replace，没有备份文件也可）
                if (File.Exists(finalPath))
                {
                    try { File.Replace(tmpPath, finalPath, destinationBackupFileName: null, ignoreMetadataErrors: true); }
                    catch { File.Delete(finalPath); File.Move(tmpPath, finalPath); }
                }
                else
                {
                    File.Move(tmpPath, finalPath);
                }

                var len = new FileInfo(finalPath).Length;
                Console.WriteLine($"[JSON保存] 已保存: {fileName}（{len} 字节） -> {finalPath}");
            }
            catch (UnauthorizedAccessException uex)
            {
                // 再次兜底到 %TEMP%
                string tempDir = EnsureDirectoryOrFallback(Path.Combine(Path.GetTempPath(), "MultiDAQ_Analysis", "MeasurementData"), force: true);
                string tempFinal = Path.Combine(tempDir, fileName);
                await WriteAllTextAsync(tempFinal, json);

                Console.WriteLine($"[JSON保存] 权限不足，降级到临时目录: {tempFinal}（原因：{uex.Message}）");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[JSON保存错误] {ex.Message}");
                throw;
            }
            finally
            {
                // 清理残留 .tmp
                try { if (File.Exists(tmpPath)) File.Delete(tmpPath); } catch { /* ignore */ }
            }
        }
        public static async Task WriteAllTextAsync(string path, string content)
        {
            // 推荐 UTF8 无 BOM
            using (var writer = new StreamWriter(path, false, new UTF8Encoding(false)))
            {
                await writer.WriteAsync(content);
                await writer.FlushAsync();
            }
        }
        /// <summary>
        /// 从 JSON 加载多轮测量数据
        /// </summary>
        public static async Task<MultiRoundMeasurementData> LoadMultiRoundDataAsync(string filePath)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(filePath))
                    throw new ArgumentException("filePath 不能为空。", nameof(filePath));

                if (!File.Exists(filePath))
                    throw new FileNotFoundException("指定的测量数据文件不存在。", filePath);

                string json;
                using (var reader = new StreamReader(filePath, new UTF8Encoding(false)))
                {
                    json = await reader.ReadToEndAsync().ConfigureAwait(false);
                }

                var obj = JsonConvert.DeserializeObject<MultiRoundMeasurementData>(json);
                if (obj == null) throw new InvalidDataException("JSON 内容无效或与模型不匹配。");
                return obj;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[JSON加载错误] {ex.Message} (路径: {filePath})");
                throw;
            }
        }

        /// <summary>
        /// 返回当前使用的数据目录（用于 UI/诊断展示）
        /// </summary>
        public static string GetCurrentDataDirectory() => DataDirectory;

        // ---------- 私有工具方法 ----------

        private static string ResolveWritableDataDirectory()
        {
            // 1) 环境变量优先（例如企业环境集中配置）
            var env = Environment.GetEnvironmentVariable(EnvDataDir);
            if (!string.IsNullOrWhiteSpace(env))
                return env;

            // 2) 当前用户（最推荐，避免权限问题）
            var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
            if (!string.IsNullOrEmpty(localAppData))
                return Path.Combine(localAppData, "MultiDAQ_Analysis", "MeasurementData");

            // 3) 机器级（需要安装时授予 Users 修改权限）
            var commonAppData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
            if (!string.IsNullOrEmpty(commonAppData))
                return Path.Combine(commonAppData, "MultiDAQ_Analysis", "MeasurementData");

            // 4) 兜底
            return Path.Combine(Path.GetTempPath(), "MultiDAQ_Analysis", "MeasurementData");
        }

        private static string EnsureDirectoryOrFallback(string dir, bool force = false)
        {
            try
            {
                if (force || !Directory.Exists(dir))
                    Directory.CreateDirectory(dir);
                // 尝试写入权限探测（创建一个空的 .perm 文件再删）
                var probe = Path.Combine(dir, ".perm");
                using (File.Create(probe, 1, FileOptions.DeleteOnClose)) { }
                return dir;
            }
            catch
            {
                // fallback 到 %TEMP%
                var temp = Path.Combine(Path.GetTempPath(), "MultiDAQ_Analysis", "MeasurementData");
                Directory.CreateDirectory(temp);
                return temp;
            }
        }

        private static string SanitizeForFileName(string name)
        {
            foreach (var c in Path.GetInvalidFileNameChars())
                name = name.Replace(c, '_');
            return name.Trim();
        }
    }
}
